from django.shortcuts import render, redirect
from plan import myform
from django.views import View
from plan import models
from django.http import QueryDict,HttpResponse,JsonResponse
from copy import deepcopy
from django.db.models import Q
from django.urls import reverse
from django.contrib import auth
from django.contrib.auth.decorators import login_required #函数的装饰器
from django.utils.decorators import method_decorator  #函数的装饰器变成方法的装饰器
from openpyxl import load_workbook
import datetime
from rbac.utils import permission
from utils.average_hours import awh  #平局工时计算
from django.forms import modelformset_factory,formset_factory
import logging

# 生成一个以当前模块名为名字的logger实例
logger = logging.getLogger(__name__)
# 生成一个名字是collect的logger实例
collect_logger = logging.getLogger('collect')


today = datetime.datetime.now().date()


# Create your views here.

def login(request):
    if request.method =='POST':
        back_dic = {'code': 200, 'errmsg': ''}  # 提前定义一个返回前端的字典
        # 1. 获取用户输入的内容
        username = request.POST.get('username')
        password = request.POST.get('password')
        is_check = request.POST.get('is_check')
        #1. 判断数据完整性
        if not all([username,password]):
            back_dic['code'] = 400,
            back_dic['errmsg'] = '参数不全，请重新输入'
            return render(request, 'templates/login1.html', locals())
            # 2. 校验用户密码是否正确
        user_obj = auth.authenticate(request, username=username, password=password)
        if user_obj:
            # 登录成功 存session 数据并回写cookie
            auth.login(request, user=user_obj)  # auth认证中间件源码

            # 执行权限组件的初始化方法
            permission.init(request, user_obj)
            if is_check:
                # 设置库存保存时常，不写默认是2周，写0是代表关闭浏览器删除
                request.session.set_expiry(7 * 24 * 60 * 60)
            else:
                request.session.set_expiry(0)
            # 跳转到首页
            return redirect(reverse('index'))
        else:
            # 登录失败
            back_dic['code'] = 400
            back_dic['errmsg'] = '邮箱或密码不正确，请重新输入'
            return render(request, 'templates/login1.html', locals())

    return render(request, 'templates/login1.html')

def index(request):
    yesterday = today - datetime.timedelta(days=1)
    yesterday1 = yesterday.strftime("%Y-%m-%d")
    #计划数量计算
    plan_queryset = models.PlanTable.objects.filter(date_num=today)
    f_line_data = 0
    c_line_data = 0
    m_line_data_day = 0
    m_line_data_night = 0
    for plan in plan_queryset:
        # print(plan.line)
        if plan.line == 'DIP_F':
            f_line_data +=plan.work_int
        if plan.line == 'DIP_C':
            c_line_data +=plan.work_int
        if plan.line == 'DIP_M':
            if plan.work_num == 'd':
                m_line_data_day += plan.work_int
            if plan.work_num == 'n':
                m_line_data_night += plan.work_int

    # 日报数量计算
    sf_line_data = 0
    sc_line_data = 0
    sm_line_data_day = 0
    sm_line_data_night = 0
    daily_production_queryset = models.DailyProduction.objects.filter(date_num=today)
    for daily in daily_production_queryset:
        if daily.line == 'DIP_F':
            sf_line_data += daily.excellent_quantity
        if daily.line == 'DIP_C':
            sc_line_data += daily.excellent_quantity
        if daily.line == 'DIP_M':
            if daily.work_num == 'd':
                sm_line_data_day += daily.excellent_quantity
            if daily.work_num == 'n':
                sm_line_data_night += daily.excellent_quantity

    #完成进度计算
    # F线完成进度计算
    f_schedule = 0
    c_schedule = 0
    m_day_schedule = 0
    m_night_schedule = 0

    if f_line_data !=0:
        f_schedule = '%.2f'% (sf_line_data / f_line_data * 100)

    if c_line_data != 0:
        c_schedule = '%.2f' % (sc_line_data / c_line_data * 100)

    if m_line_data_day  != 0:
        m_day_schedule = '%.2f'%(sm_line_data_day / m_line_data_day * 100)

    if m_line_data_night  != 0:
        m_night_schedule = '%.2f'%(sm_line_data_night / m_line_data_night * 100 )

    return render(request,'templates/index.html',locals())

def register(request):
    form_obj = myform.MyregForm()
    if request.method == 'POST':
        # ajax前后端交互，提前定义个字典
        back_dic = {'code': 200, 'errmsg': ''}
        #校验数据是否合法
        form_obj = myform.MyregForm(request.POST)
        #判断数据是否合法
        if form_obj.is_valid():
            print(form_obj.cleaned_data)  #{'username': 'chen', 'password': 'chen1234', 'confirm_password': 'chen1234', 'email': '135@163.com'}
            #只校验form组件里面有的字段，多给的它不要

            clean_data = form_obj.cleaned_data #将校验通过的数据字典复制给一个变量
            #将字典里面的confirm_password 键值对删除
            clean_data.pop('confirm_password')  #{'username': 'chen', 'password': 'chen1234', 'email': '135@163.com'}
            #用户头像
            file_obj = request.FILES.get('avatar')
            '''针对用户头像一定要判断是否传值，不能直接添加到字典中'''
            if file_obj:
                clean_data['avatar'] = file_obj
            #直接操作数据库保存数据
            models.UserInfo.objects.create_user(**clean_data)
            back_dic['url'] = '/login/'
        else:
            back_dic['code'] = 400
            back_dic['errmsg'] = form_obj.errors

        return JsonResponse(back_dic)

    return render(request,'templates/register.html',locals())

@login_required
def logout(request):
    auth.logout(request)
    return redirect('/login/')

'''
图片相关的模块pip3 install pillow

Image, 生成图片
ImageDraw,能够在图片上乱涂乱画
ImageFont，控制字体样式

'''
from PIL import Image,ImageDraw,ImageFont
import random
from io import BytesIO,StringIO

'''
内存管理器模块
BytesIO,临时帮你存储数据 返回的时候数据是二进制
StringIO,临时帮你存储数据 返回的时候数据是字符串
'''
'''
def get_random():
    return random.randint(0,255),random.randint(0,255),random.randint(0,255)

def get_code(request):
    #推导步骤1：直接获取后端现成的图片二进制数据发送给前端
    # with open(r'static/img/default2_urP9jYf.png','rb') as f:
    #     data = f.read()
    # return HttpResponse(data)

    # #推导步骤2：利用pillow模块动态产生图片
    # # img_obj = Image.new('RGB',(350,35),'green')
    # img_obj = Image.new('RGB',(350,35),get_random())
    # #先将图片保存起来
    # with open('xx1.png','wb') as f:
    #     img_obj.save(f,'png')
    # #再将图片对象读取出来
    # with open('xx1.png','rb')as f:
    #     data = f.read()
    # return HttpResponse(data)

    #推导步骤3：文件存储繁琐，IO操作效率低，  借助于内存管理器模块
    # img_obj = Image.new('RGB', (350, 35), get_random())
    # io_obj = BytesIO()  #生成一个内存管理器对象  你可以看成是文件句柄
    # img_obj.save(io_obj,'png')
    # return HttpResponse(io_obj.getvalue())  #从内存管理器中读取二进制的图片数据返回给前端

    # 推导步骤4：写图片验证码
    img_obj = Image.new('RGB', (350, 35), get_random())
    img_draw = ImageDraw.Draw(img_obj)  #产生一个画笔对象
    img_font = ImageFont.truetype(r'static/font/111.ttf',30) #设置字体 大小

    #写随机验证码 五位数的随机验证码  数字 小写字母 大写字母
    code = ''
    for i in range(5):
        random_upper = chr(random.randint(65,90))
        random_lower = chr(random.randint(97,122))
        random_int = str(random.randint(0,9))
        #从上面三个里面随机选择一个
        tmp = random.choice([random_upper,random_lower,random_int])
        #将产生的随机字符串写入到图片上
        """
        为什么一个个写而不是生成好了之后再写
        因为一个个写能够控制每个字体的间隙 而生产好之后再写的话
        间隙就没法控制了
        """
        img_draw.text((i*60,0),tmp,get_random(),img_font)
        #拼接随机字符串
        code +=tmp
    print(code)
    # 随机的验证码在登录的视图函数里面需要用到 要比对 所以要找地方存起来并且其他视图函数也能找到
    request.session['code'] = code
    io_obj = BytesIO()
    img_obj.save(io_obj,'png')
    return HttpResponse(io_obj.getvalue())
'''
@login_required
def set_password(request):
    back_dic = {'code': 200, 'errmsg': ''}
    if request.is_ajax():
        if request.method == 'POST':
            old_password = request.POST.get('old_password')
            new_password = request.POST.get('new_password')
            confirm_password = request.POST.get('confirm_password')
            is_right = request.user.check_password(old_password)  #确认旧密码是否正确
            if is_right:
                if new_password == confirm_password:
                    request.user.set_password(new_password)  #修改密码
                    request.user.save()  #保存密码  一定一定不能忘记
                    back_dic['errmsg'] = '修改成功'
                else:
                    back_dic['code'] = 400
                    back_dic['errmsg'] ='两次密码不一致'
            else:
                back_dic['code'] = 400
                back_dic['errmsg'] = '原密码不正确不能修改，请重试！'

    return JsonResponse(back_dic)


#添加和编辑订单
@login_required
def add_order(request,edit_id=None):
    edit_obj = models.Order.objects.filter(id=edit_id).first()
    form_obj = myform.OrderForm(instance=edit_obj)
    if request.method == 'POST':
        #实例化前端纯过来的出书表单对象
        form_obj = myform.OrderForm(request.POST,instance=edit_obj)
        if form_obj.is_valid():
            #存入数据库
            # form_obj.save()
            if edit_id:  # 则是修改
                print(request.POST)
                data_number = request.POST.get('data_number')
                # 1. 如果计划已经安排，修改了之后还要修改计划的工单数量
                if edit_obj.is_plan:
                    plan_objs = models.PlanTable.objects.filter(order=edit_id,order__is_production=False)
                    if plan_objs.first() is None:
                        return HttpResponse('工单不存在或已生产，不能修改！')

                    #没有开始生产，则修改数量
                    form_obj.save()
                    models.PlanTable.objects.filter(order=edit_id).update(Lot=data_number)
                    for plan_obj in plan_objs:
                        work_process = plan_obj.work_process
                        edit_plan_obj = plan_objs.filter(work_process=work_process)
                        # edit_plan_obj = models.PlanTable.objects.filter(order=edit_id,work_process=work_process)
                        # 计划已安排只有1条，没有分析，则直接修改数量
                        if edit_plan_obj.count() == 1:
                            edit_plan_obj.update(work_int = data_number)

                        # 如减少的工单所在的工程面，不止1条，分批生产情况，则只留第一条修改成工单的数量，其他的直接干掉删除
                        else:
                            edit_id_list = []
                            for i in edit_plan_obj:
                                edit_id_list.append(i.id)
                            only_id = edit_id_list.pop(0)
                            models.PlanTable.objects.filter(id__in=edit_id_list).delete()
                            models.PlanTable.objects.filter(id=only_id).update(work_int = data_number)
                else:
                    form_obj.save()
            else:
                code = request.POST.get('code')
                sys_code = models.Order.objects.filter(code=code).first()
                if sys_code:
                    return HttpResponse('工单生产指示No已存在，请更改！！')
                form_obj.save()
                #需要更新计算这些生产数量 todo
                # 2.如果未安排，则直接修改保存
            #跳转到客户列表页面
            return redirect('/plan/order_list/')
            # url = reverse('order_list')
            # redirect(url)
    return render(request,'templates/add_order.html',locals())


# order 删除功能 这里删除功能是is_delete = Ture
def delete_order(request,order_id):
    order_obj = models.Order.objects.filter(id=order_id).update(is_delete=True)
    return redirect(reverse('order_list'))

#分页器导入
from utils.mypage1 import Pagination

class OrderListView(View):
    @method_decorator(login_required)  # 函数的装饰器编程方法的装饰器
    def get(self,request):
        url_prefix = request.path_info
        # print(request.path_info,type(request.path_info))
        # print(request.get_full_path())
        # print(request.GET)
        qd = deepcopy(request.GET)
        qd._mutable = True  # 修改属性，可以拼接url查询字符串参数
        data = models.Order.objects.filter(is_delete=False)
        # 1. 获取所有的客户信息

        # 获取检索的关键字，取不到为空
        query_q = request.GET.get('query', '')

        # 通过关键字检索
        queryset = data.filter(
            Q(code__contains=query_q) | Q(customer__small_name__contains=query_q) | Q(sku__name__contains=query_q)
        )

        current_page = request.GET.get('page', 1)  # url关键字传参
        all_count = queryset.count()
        # 实例对象
        # 1 传值生成对象
        page_obj = Pagination(current_page=current_page, total_count=all_count, url_prefix=url_prefix, query_dict=qd,
                              per_page=20)

        # 2 直接对总数据进行切片操作
        # page_queryset = customer_queryset[page_obj.start:page_obj.end]
        customer_list = queryset[page_obj.start:page_obj.end]
        # 2. 在页面上展示出来

        # data = customer_queryset[page_obj.start:page_obj.end]
        # # 2. 在页面上展出出来
        # 3 返回之前的页面
        # 3.1 获取当前也请求的带query参数的url
        url = request.get_full_path()

        # 3.2 生产一个空QueryDict对象
        query_params = QueryDict(mutable=True)

        # 3.3 给添加一个next键值对
        query_params['next'] = url

        # 3.4 利用QUeryDict内置的方法编码成URL
        next_url = query_params.urlencode()
        return render(request,'templates/order_list.html',locals())

# 批量上传工单list
def order_upload(request):
    current_time = datetime.datetime.now()
    yyyymmdd_time = current_time.strftime("%Y%m%d")

    print(yyyymmdd_time)
    print(today)

    if request.method =='POST':
        file = request.FILES.get('name_file')
        if file == None:
            return HttpResponse('上传的空数据，请重新确认！！')
        wb = load_workbook(file)
        sheet1 = wb.active
        L = []
        for row1 in sheet1:
            row_list1 = []
            for i in row1:
                row_list1.append(i.value)
            L.append(row_list1)
        order_obj = models.Order.objects.filter(item_date=today).last()
        print(order_obj)
        next_num = 0
        if order_obj is None:
            next_num = 1
        else:
            obj_num = order_obj.code[8:]
            next_num = int(obj_num) + 1
        if len(L) < 2:
            return HttpResponse('传入的空数据，请返回重新修改！')
        order_objs = []
        for i in L[1:]:
            code = yyyymmdd_time + "{:03d}".format(next_num)
            sku_obj = models.SKU.objects.filter(name=i[0]).first()
            new_order_obj = models.Order(
                code = code,
                sku = sku_obj,
                customer = sku_obj.cust,
                data_number = i[1],
                shipping_date = i[3],
            )
            order_objs.append(new_order_obj)
            next_num += 1
            # print(code,sku_obj)
            # print(i)
        models.Order.objects.bulk_create(order_objs)
        return redirect(reverse('order_list'))

    return HttpResponse('无get请求返回！')


#添加计划
@login_required
def add_plan(request,order_id):
    print(order_id,type(order_id))
    order_obj = models.Order.objects.filter(id=order_id,is_delete=False,is_plan=False).first()
    sku = order_obj.sku
    sku_process = models.ProcessFlow.objects.filter(sku=sku).values()
    flow_process = [i.get('flow') for i in sku_process]
    if flow_process is None:
        return HttpResponse('机种%s没有添加工序拼接数据，请添加后再执行操作！' % sku.name)
    #获取机种的工程list，适合批量生成计划
    if flow_process[0] is False:
        return HttpResponse('机种%s没有添加工序拼接数据，请添加后再执行操作！'%sku.name)
    flow_list = flow_process[0].split('_')
    print(flow_list)
    data_list = []
    for pro in flow_list:
        # create_list = {}
        # #生产指示单号
        # create_list['plan_code'] = order_obj.code
        # #客户
        # create_list['customer'] = order_obj.customer
        # #机种
        # create_list['sku'] = order_obj.sku
        # #工单数量，Lot
        # create_list['Lot'] = order_obj.data_number
        # #生产工程面
        # create_list['work_process'] = pro
        # # 生产线别 根据 机种名+工程面 获取默认先别
        sku_line_obj = models.SkuProcessLineCpa.objects.filter(sku=order_obj.sku,process=pro).first()
        sku_line = ''
        if sku_line_obj is None:
            sku_line = pro
        else:
            sku_line = sku_line_obj.line
        # create_list['line'] = sku_line
        # #生产数量 ，默认工单数，计划修改中在修改
        # create_list['work_int'] = order_obj.data_number
        # create_list['plan_pro_code'] = order_obj.code + '_' + pro + '_' + '001'
        # data_list.append(create_list)

        #按线别取制造部门待完善
        # production_department_queryset = models.LineProductionDepartment.objects.filter(line=sku_line)
        # # cc = production_department_queryset.department
        #
        # c = [i.department for i in production_department_queryset]
        # print(c,type(c))
        # print(production_department_queryset,type(production_department_queryset))
        # production_department_obj = production_department_queryset.get('department')
        # print(production_department_obj)

        #按工程取制造部门
        production_department_queryset = models.ProcessProductionDepartment.objects.filter(process=pro).first()
        # print(production_department_queryset,type(production_department_queryset))
        try:
            department = production_department_queryset.department
        except Exception as e:
            department = '制造一课'  #如果没有，默认写在一课，后面修改计划是修改
            print('工程对应的制造部门不存在',e)
        # print(department)

        data_obj = models.PlanTable.objects.filter(order_id=order_obj.id,sku=order_obj.sku,work_process= pro).first()
        if data_obj ==None:
            plan_obj = models.PlanTable.objects.create(
                order_id = order_obj.id,
                plan_code = order_obj.code,
                customer = order_obj.customer,
                sku=order_obj.sku,
                Lot = order_obj.data_number,
                work_process= pro,
                line = sku_line,
                work_int = order_obj.data_number,
                plan_pro_code=order_obj.code + '_' + pro + '_' + '001',
                production_department = department,
                spd = order_obj.shipping_date,
                working_hours = '24'
               )
        data = models.DailyStatus.objects.filter(sku = order_obj.sku,order_id = order_obj.id,process = pro).first()
        if data == None:
            daily_status_obj = models.DailyStatus.objects.create(
                sku = order_obj.sku,
                order_id = order_obj.id,
                process = pro,
                Lot=order_obj.data_number,
            )
        else:
            daily_status_obj = models.DailyStatus.objects.update(
                Lot=order_obj.data_number,
            )
    models.Order.objects.filter(id=order_id).update(is_plan=True)
    # sku_process_flow = sku_process

    next_url = request.GET.get('next', reverse('order_list'))
    return redirect(next_url)

    # return redirect('/plan/order_list/')


class PlanListView(View):
    @method_decorator(login_required)  # 函数的装饰器编程方法的装饰器
    def get(self,request):

        zuotian = datetime.datetime.now().date() - datetime.timedelta(days=1)

        url_prefix = request.path_info
        # print(request.path_info,type(request.path_info))
        # print(request.get_full_path())
        # print(request.GET)
        qd = deepcopy(request.GET)
        qd._mutable = True  # 修改属性，可以拼接url查询字符串参数
        data = models.PlanTable.objects.filter(date_num__gte=zuotian).order_by('date_num','line','production_line_num','sku')
        # 1. 获取所有的客户信息

        # 获取检索的关键字，取不到为空
        query_q = request.GET.get('query', '')

        # 通过关键字检索
        queryset = data.filter(
            Q(plan_code__contains=query_q) | Q(customer__small_name__contains=query_q) | Q(sku__name__contains=query_q) | Q(production_department__contains=query_q)
            | Q(line__contains=query_q)
        )

        current_page = request.GET.get('page', 1)  # url关键字传参
        all_count = queryset.count()
        # 实例对象
        # 1 传值生成对象
        page_obj = Pagination(current_page=current_page, total_count=all_count, url_prefix=url_prefix, query_dict=qd,
                              per_page=50)

        # 2 直接对总数据进行切片操作
        # page_queryset = customer_queryset[page_obj.start:page_obj.end]
        plan_list = queryset[page_obj.start:page_obj.end]
        # 2. 在页面上展示出来

        # data = customer_queryset[page_obj.start:page_obj.end]
        # # 2. 在页面上展出出来
        # 3 返回之前的页面
        # 3.1 获取当前也请求的带query参数的url
        url = request.get_full_path()

        # 3.2 生产一个空QueryDict对象
        query_params = QueryDict(mutable=True)

        # 3.3 给添加一个next键值对
        query_params['next'] = url

        # 3.4 利用QUeryDict内置的方法编码成URL
        next_url = query_params.urlencode()
        return render(request, 'templates/plan_list.html', locals())


@login_required
def edit_plan(request,plan_id=None):
    plan_obj1 = models.PlanTable.objects.filter(id=plan_id).first()
    form_obj = myform.PlanTableForm(instance=plan_obj1)
    disabled_list = ['订单id','订单指示NO','客户','生产机种品番','工单数量','生产工程面','工程生产知识NO']
    if request.method == 'POST':
        form_obj = myform.PlanTableForm(request.POST, instance=plan_obj1)
        print(request.POST)
        #获取订单数量
        Lot = request.POST.get('Lot')
        #获取计划生产数量
        work_int = request.POST.get('work_int')
        #查询数据库，如果当前订单号，对应的工程面只有这1条记录，说明这个工单是一次安排完的
        #          如果当前订单号，对应的工程面不止1条记录，说明这个工单是多次安排完的
                    #多次需要获取条数，分批要在此基础上，编号+1，并且几次的生产数量总和要等于工单数

        # print(Lot,type(Lot))
        # print(work_int,type(work_int))
        if form_obj.is_valid():
            #存入数据库
            form_obj.save()
            #跳转到客户列表页面
        if not Lot == work_int:  #如相等，且编号只有一个，说明修改的不是数量,修改的其他字段
            #如果数量不相等，获取plan_pro_code 字段，订单号_工程_编号
            plan_pro_code = request.POST.get('plan_pro_code')
            #根据_切割，分割成订单号、工程、编号
            plan_str = plan_pro_code.split('_')
            print(plan_str)
            #查询数据库，根据订单号和工程
            plan_obj = models.PlanTable.objects.filter(plan_code=plan_str[0],work_process=plan_str[1])

            #获取上批的交货日期
            spd_date = request.POST.get('spd')

            #判断同一个订单号的一个工程有几条记录
            count = plan_obj.count()
            # print(count)
            # print('*'*90)
            #count = 1是，分一批，操作是

            if count == 1:
                plan_obj = plan_obj.first()
                new_work_int = int(Lot) - int(work_int)
                #生产数量小于订单数量，说明是分批生产
                #把当前对应拷贝一份，作为分批的一条数据
                #修改拷贝的生产数量  订单数-第一条生产数量-第二条生产数量...=要生成的生产数
                # new_query_dict = deepcopy(request.POST)
                # new_query_dict._mutable = True  # 修改属性，可以拼接url查询字符串参数
                # #生产数量修改
                # new_query_dict['work_int'] = new_work_int
                #生产编号修改
                num = int(plan_str[2])
                num = num + count
                new_plan_pro_code = plan_str[0] + '_' +plan_str[1] + '_' + '00' + str(num)
                new_plan_obj = models.PlanTable.objects.create(
                order_id = plan_obj.order.id,
                plan_code = plan_obj.plan_code,
                customer = plan_obj.customer,
                sku = plan_obj.sku,
                Lot = plan_obj.Lot,
                work_process = plan_obj.work_process,
                line = plan_obj1.line,
                work_int = new_work_int,
                plan_pro_code = new_plan_pro_code,
                working_hours = '20.4',
                production_department = plan_obj.production_department,
                spd= spd_date,
                    )
            #如果count 》 1，需要计算生产数量之和之后再增加一条剩下的数量。
            elif count > 1:
                work_int_list = []
                for i in plan_obj:
                    work_int_list.append(int(i.work_int))
                total = 0
                for num in work_int_list:
                    total += num
                if total == int(Lot):
                    return redirect('/plan/plan_list/')
                if not total < int(Lot):
                    return HttpResponse('生产数量大于工单数，请返回确认！')
                new_work_int = int(Lot) - total
                plan_obj = plan_obj.first()
                #获取工单的工程指示No
                # pro_num = int(plan_str[2])
                pro_num = 1 + count
                new_plan_pro_code = plan_str[0] + '_' + plan_str[1] + '_' + '00' + str(pro_num)
                new_plan_obj = models.PlanTable.objects.create(
                    order_id=plan_obj.order.id,
                    plan_code=plan_obj.plan_code,
                    customer=plan_obj.customer,
                    sku=plan_obj.sku,
                    Lot=plan_obj.Lot,
                    work_process=plan_obj.work_process,
                    line=plan_obj1.line,
                    work_int=new_work_int,
                    plan_pro_code=new_plan_pro_code,
                    working_hours= '20.4' ,
                    production_department=plan_obj1.production_department,
                    spd=spd_date,
                )
        else:
            # 跳转到添加前的页面
            next_url = request.GET.get('next', reverse('plan_list'))
            return redirect(next_url)
        next_url = request.GET.get('next', reverse('plan_list'))
        return redirect(next_url)
        # url = reverse('order_list')
        # redirect(url)

    return render(request,'templates/edit_plan.html',locals())


#合并计划
class MergePlanView(View):
    @method_decorator(login_required)  # 函数的装饰器编程方法的装饰器
    def get(self,request,plan_id=None):
        plan_obj = models.PlanTable.objects.filter(id=plan_id).first()
        # print(plan_obj.plan_pro_code)
        plan_str_pro = plan_obj.plan_pro_code
        plan_str = plan_str_pro.split('_')
        plan_list = models.PlanTable.objects.filter(plan_code=plan_str[0],work_process=plan_str[1])
        return render(request, 'templates/merge_plan.html', locals())

    def post(self,request,plan_id=None):
        # 1. 获取前端需要操作的数据
        action = request.POST.get('action')
        cid = request.POST.getlist('cid')  # 批量修改用getlist get只能取最后一个  要操作的客户id
        if len(cid) == 0:
            return HttpResponse('没有选中需要合并的计划按钮！')
        print(action,cid)
        # 利用反射封装
        if not hasattr(self, '_{}'.format(action)):
            return HttpResponse('没有此方法！！')
        res = getattr(self, '_{}'.format(action))(cid)
        if res:
            return res
        # return self.get()
        # 跳转到添加前的页面
        next_url = request.GET.get('next', reverse('plan_list'))
        return redirect(next_url)

    #合并计划操作
    def _to_total(self,cid):
        query_set = models.PlanTable.objects.filter(id__in=cid)
        work_list_num = []
        for data in query_set:
            work_list_num.append(data.work_int)
        total = sum(work_list_num)
        only_id = cid.pop(0)
        models.PlanTable.objects.filter(id__in=cid).delete()
        models.PlanTable.objects.filter(id=only_id).update(work_int=total)

# 修改生产顺序
@login_required
def seq(request,plan_id):
    plan_obj = models.PlanTable.objects.filter(id=plan_id).first()
    form_obj = myform.SequencePlanTableForm(instance=plan_obj)
    if request.method == 'POST':
        form_obj = myform.SequencePlanTableForm(request.POST, instance=plan_obj)
        if form_obj.is_valid():
            #存入数据库
            form_obj.save()
            #跳转到客户列表页面
            # 跳转到添加前的页面
            next_url = request.GET.get('next', reverse('plan_list'))
            return redirect(next_url)
            # url = reverse('order_list')
            # redirect(url)
        else:
            return HttpResponse('数据不合法！')

    return render(request,'templates/seq.html',locals())

# 计划删除功能
def delete_plan(request,plan_id):
    plan_obj = models.PlanTable.objects.filter(pk=plan_id).first()
    # print(plan_obj.work_int,type(plan_obj.work_int))
    if plan_obj.work_int == 0:
        plan_obj.delete()
        return redirect(reverse('plan_list'))
    # plan_obj1 = models.PlanTable.objects.filter(order__is_delete=True)
    # print(plan_obj1)
    # return HttpResponse('测试中')
    return HttpResponse('生产数量不为0，不能删除')


#添加生产日报
@login_required
def add_daily_production(request,plan_id=None):
    plan_obj = models.PlanTable.objects.filter(id=plan_id).first()
    # print(plan_obj)
    # daily_obj = models.DailyProduction.objects.filter(sku=plan_obj.sku).first()
    # print(daily_obj)
    form_obj = myform.DailyProductionForm(initial={
        'sku': plan_obj.sku,
        'plan_table': plan_obj.id,
        'order': plan_obj.order.id,
        'line': plan_obj.line,
        'work_process': plan_obj.work_process,
        'completed_quantity':plan_obj.work_int,
        'production_department':plan_obj.production_department,

    })
    if request.method == 'POST':
        print(request.POST)
        form_obj = myform.DailyProductionForm(request.POST,form_obj)
        if form_obj.is_valid():
            # 1. 需要累计数量存入数量管控表
            # 1.1 获取request提交过来的sku_id,order_id,process
            # item_query_dict = request.POST
            sku_id = request.POST.get('sku')
            order_id = request.POST.get('order')
            process = request.POST.get('work_process')
            #完成数：
            completed_quantity = request.POST.get('completed_quantity')
            #制造报废数
            manufacturing_scrap = request.POST.get('manufacturing_scrap')
            # 技术报废数
            technical_scrap = request.POST.get('technical_scrap')
            # 解析报废数
            analysis_scrap = request.POST.get('analysis_scrap')
            # 单品报废数
            item_scrap = request.POST.get('item_scrap')

            # 合计报废数量
            total_scrap = int(manufacturing_scrap) +int(technical_scrap) +int(analysis_scrap) +int(item_scrap)
            # 良品数
            excellent_quantity = request.POST.get('excellent_quantity')
            # 不良数不参与校验，可能维修成良品
            #生产部门
            production_department = request.POST.get('production_department')
            # 1.2 按获取的三个参数查询 DailyStatus
            daily_status_obj = models.DailyStatus.objects.filter(sku_id=sku_id, order_id=order_id,
                                                                 process=process)
            # 1.3 获取 daily_status_obj中需要校验的参数 完成数，报废数，工单数
            if daily_status_obj.first() is None:
                return HttpResponse('之前的机种，更换一个测试！！')
            Lot = daily_status_obj.first().Lot
            # 已输入过的完成品数
            accumulated_completed_qty = daily_status_obj.first().accumulated_completed_qty
            # 已输入过的报废数
            accumulated_scrap_qty = daily_status_obj.first().accumulated_scrap_qty

            #生产数量合计 良品数 + 报废数
            completed_total = int(excellent_quantity) + total_scrap + int(accumulated_completed_qty) + int(accumulated_scrap_qty)
            if Lot >= completed_total:
                daily_status_obj.update(
                    accumulated_completed_qty = int(excellent_quantity) + int(accumulated_completed_qty),
                    accumulated_scrap_qty = total_scrap + int(accumulated_scrap_qty),
                    department = production_department,
                )
                form_obj.save()
                return redirect('/plan/daily_list/')
            else:
                return HttpResponse('数据不合法，重新检查良品数和报废数是否超出工单数！')
    return render(request, 'templates/add_daily_production.html', locals())


#编辑日报
def edit_daily(request,daily_id=None):
    daily_obj = models.DailyProduction.objects.filter(id=daily_id).first()
    form_obj = myform.DailyProductionForm(instance=daily_obj)
    if request.method == 'POST':

        form_obj = myform.DailyProductionForm(request.POST, instance=daily_obj)
        if form_obj.is_valid():

            print(request.POST)
            # 1. 需要累计数量存入数量管控表
            # 1.1 获取request提交过来的sku_id,order_id,process
            item_query_dict = request.POST
            sku_id = item_query_dict.get('sku')
            order_id = item_query_dict.get('order')
            work_process = item_query_dict.get('work_process')
            # 修改日报的良品数量
            excellent_quantity = int(item_query_dict.get('excellent_quantity'))
            # 制造报废数
            manufacturing_scrap = request.POST.get('manufacturing_scrap')
            # 技术报废数
            technical_scrap = request.POST.get('technical_scrap')
            # 解析报废数
            analysis_scrap = request.POST.get('analysis_scrap')
            # 单品报废数
            item_scrap = request.POST.get('item_scrap')

            # 合计报废数量 修改日报的报废数量
            total_scrap = int(manufacturing_scrap) + int(technical_scrap) + int(analysis_scrap) + int(item_scrap)

            # 修改日报的报废数量
            # scrap_quantity = int(item_query_dict.get('scrap_quantity'))

            # 修改日报的不良数量
            defective_qty = int(item_query_dict.get('defective_qty'))

            #Lot数量获取
            order_obj = models.Order.objects.filter(id=order_id).first()
            Lot = order_obj.data_number

            daily_production_obj = models.DailyProduction.objects.filter(sku_id=sku_id, order_id=order_id,
                                                                         work_process=work_process)
            # 计算日报输入的良品数量 除当前id的除外
            #良品数量累计，不包含当前修改的id
            total_excellent_quantity = 0
            # 制造报废数量累计，不包含当前修改的id
            total_manufacturing_scrap = 0

            # 技术报废数量累计，不包含当前修改的id
            total_technical_scrap = 0
            # 解析报废数量累计，不包含当前修改的id
            total_analysis_scrap = 0
            # 单品报废数量累计，不包含当前修改的id
            total_item_scrap = 0

            #不良数量累计，不包含当前修改的id
            total_defective_qty = 0
            for i in daily_production_obj:
                if i.id != int(daily_id):
                    total_excellent_quantity += i.excellent_quantity
                    total_manufacturing_scrap += i.manufacturing_scrap
                    total_technical_scrap +=i.technical_scrap
                    total_analysis_scrap =+ i.analysis_scrap
                    total_item_scrap += i.item_scrap
                    total_defective_qty += i.defective_qty
            print(total_excellent_quantity)
            scrap_quantity = total_manufacturing_scrap + total_technical_scrap + total_analysis_scrap + total_item_scrap
            print(scrap_quantity)
            print('*' * 90)
            #         修改日报的良品数量      修改id的合计报废    修改id以外的合计良品数     修改id以外的合计报废数
            if Lot >= excellent_quantity + total_scrap + total_excellent_quantity + scrap_quantity:
                form_obj.save()
                daily_status_obj = models.DailyStatus.objects.filter(sku_id=sku_id, order_id=order_id,
                                                                     process=work_process).update(
                    accumulated_completed_qty = excellent_quantity + total_excellent_quantity,
                    accumulated_scrap_qty =  total_scrap + scrap_quantity,
                    accumulated_defects_qty = defective_qty + total_defective_qty,
                )
                return redirect('/plan/daily_list/')
                # # 获取DailyProduction id order work_process相同的，计算良品数量和报废数量书否超出工单数
                # # 1.2 按获取的三个参数查询 DailyStatus
                # daily_status_obj = models.DailyStatus.objects.filter(sku_id=sku_id, order_id=order_id,
                #                                                      process=work_process).first()
                # # 1.3 获取 daily_status_obj中需要校验的参数 完成数，报废数，工单数
                # Lot = daily_status_obj.Lot
                # accumulated_completed_qty = daily_status_obj.accumulated_completed_qty
                # accumulated_defects_qty = daily_status_obj.accumulated_defects_qty
                # accumulated_scrap_qty = daily_status_obj.accumulated_scrap_qty
                #
                # print(Lot, accumulated_completed_qty, accumulated_defects_qty, accumulated_scrap_qty)
                # form_obj.save()
            else:
                return HttpResponse('输入的良品数量和报废数量总和超出了Lot数量，请重新输入！！')

    def awh(p_num, hours, number):
        '''

        :param p_num: 生产的人数
        :param hours: 生产的时间（单位是小时）
        :return: 单台时间（单位是分钟）
        '''
        total_minute = p_num * 60 * hours  # 人数换算成工时分钟总和
        average_work_hours = '%.4f' % (total_minute / number)
        return average_work_hours
    return render(request, 'templates/add_daily_production.html', locals())

#日报列表
class DailyListView(View):
    def get(self,request):
        url_prefix = request.path_info
        qd = deepcopy(request.GET)
        qd._mutable = True  # 修改属性，可以拼接url查询字符串参数
        data = models.DailyProduction.objects.all().order_by('date_num','line','sku')
        # 获取检索的关键字，取不到为空
        query_q = request.GET.get('query', '')

        # 通过关键字检索
        queryset = data.filter(
             Q(sku__name__contains=query_q) | Q(line__contains=query_q)
        )

        current_page = request.GET.get('page', 1)  # url关键字传参
        all_count = queryset.count()
        # 实例对象
        # 1 传值生成对象
        page_obj = Pagination(current_page=current_page, total_count=all_count, url_prefix=url_prefix, query_dict=qd,
                              per_page=50)

        # 2 直接对总数据进行切片操作
        # page_queryset = customer_queryset[page_obj.start:page_obj.end]
        daily_list = queryset[page_obj.start:page_obj.end]
        # 2. 在页面上展示出来

        # data = customer_queryset[page_obj.start:page_obj.end]
        # # 2. 在页面上展出出来
        # 3 返回之前的页面
        # 3.1 获取当前也请求的带query参数的url
        url = request.get_full_path()

        # 3.2 生产一个空QueryDict对象
        query_params = QueryDict(mutable=True)

        # 3.3 给添加一个next键值对
        query_params['next'] = url

        # 3.4 利用QUeryDict内置的方法编码成URL
        next_url = query_params.urlencode()

        return render(request,'templates/daily_list.html',locals())

#工时列表
def st(request):
    st_list = models.ST.objects.filter().order_by('sku','pro')
    return render(request,'templates/st.html',locals())

#编辑添加工时
def edit_st(request,st_id=None):
    st_obj = models.ST.objects.filter(id = st_id).first()
    form_obj = myform.STForm(instance=st_obj)
    if request.method == 'POST':
        # print(request.POST)
        form_obj = myform.STForm(request.POST,instance=st_obj)
        if form_obj.is_valid():

            form_obj.save()
            return redirect(reverse('st_list'))
    #添加单台标准工时 /编辑单台工时合并
    return render(request,'templates/add_st.html',locals())


def search(request,plan_id=None):
    plan_obj = models.PlanTable.objects.filter(pk=plan_id).first()
    flow_obj = models.ProcessFlow.objects.filter(sku=plan_obj.sku).first()
    cpa = models.SkuProcessLineCpa.objects.filter(sku=plan_obj.sku,process=plan_obj.work_process)
    return render(request,'templates/search.html',locals())



# class BulkEditPlan(View):
#     FormSet = modelformset_factory(models.PlanTable, myform.PlanTableForm, extra=0)
#     def get(self,request,plan_id):
#         # 查找到 所选的plan_id的数据
#         # 1. 从post提交过来的数据里找action 和 勾选的计划的id
#         cid = request.GET.getlist('cid')
#         action = request.GET.get('action')
#
#         data = models.PlanTable.objects.filter(id__in=cid)
#
#         formset_obj = self.FormSet(queryset=data)
#         return render(request,'templates/bulk_edit_plan.html',locals())
#     def post(self,request):
#         # 2. 利用反射执行指定的动作
#         formset_obj = self.FormSet(request.POST,queryset=data)

#批量修改计划
def bulk_edit_plan(request):
    # 查找到 所选的plan_id的数据
    # 1. 从post提交过来的数据里找action 和 勾选的计划的id
    cid = request.GET.getlist('cid')
    action = request.GET.get('action')
    data = models.PlanTable.objects.filter(id__in=cid)
    FormSet = modelformset_factory(models.PlanTable, myform.PlanTableForm, extra=0)
    formset_obj = FormSet(queryset=data)

    if request.method == 'POST':
        formset_obj = FormSet(request.POST,queryset=data)
        if formset_obj.is_valid():
            formset_obj.save()
            print('formset修改完成！')
            logger.info('formset_obj  -- >保存成功！')
            return redirect(reverse('plan_list'))
    return render(request, 'templates/bulk_edit_plan.html', locals())


def daily_status(request):
    url_prefix = request.path_info
    qd = deepcopy(request.GET)
    qd._mutable = True  # 修改属性，可以拼接url查询字符串参数
    data = models.DailyStatus.objects.filter().order_by('order','process','department' )
    # 获取检索的关键字，取不到为空
    query_q = request.GET.get('query', '')

    # 通过关键字检索
    queryset = data.filter(
        Q(sku__name__contains=query_q) | Q(order__code__contains=query_q) | Q(department__contains=query_q)
    )

    current_page = request.GET.get('page', 1)  # url关键字传参
    all_count = queryset.count()
    # 实例对象
    # 1 传值生成对象
    page_obj = Pagination(current_page=current_page, total_count=all_count, url_prefix=url_prefix, query_dict=qd,
                          per_page=50)

    # 2 直接对总数据进行切片操作
    # page_queryset = customer_queryset[page_obj.start:page_obj.end]
    daily_status_list = queryset[page_obj.start:page_obj.end]
    # 2. 在页面上展示出来

    # data = customer_queryset[page_obj.start:page_obj.end]
    # # 2. 在页面上展出出来
    # 3 返回之前的页面
    # 3.1 获取当前也请求的带query参数的url
    url = request.get_full_path()

    # 3.2 生产一个空QueryDict对象
    query_params = QueryDict(mutable=True)

    # 3.3 给添加一个next键值对
    query_params['next'] = url

    # 3.4 利用QUeryDict内置的方法编码成URL
    next_url = query_params.urlencode()

    return render(request, 'templates/daily_status_list.html', locals())












'''
plan_obj 编辑不可以修改的字段
订单id
订单指示NO
客户
生产机种品番
工单数量
生产工程面
工程生产知识NO

plan_obj 编辑可以修改的字段
生产线别 1
生产班次 1
生产数量 2
说明 1 2
计划完成时间 2
生产顺序 1
班检查能力 2
检查当前LOT时间 2
编辑


'''

